//数据计算模块
class Calculate{
    /**
     * [computeCount 计算注数]
     * @param  {number} active    [当前选中的号码的个数]
     * @param  {string} play_name [当前的玩法标识,如R2,即任二]
     * @return {number}           [注数]
     */
    computeCount(active,play_name){
        let count=0;
        const exist=this.play_list.has(play_name); //判断玩法列表里面是否有这样的玩法, es6的set形式，这样用has()方法就能轻松的判断有没有某个键值
        const arr=new Array(active).fill('0'); //生成长度为active的数组，并填充为0。这两个都是es6的新特性
        if(exist && play_name.at(0)==='r'){
            count=Calculate.combine(arr,play_name.split('')[1]).length;
        }
        return count;   //返回值是计算好的注数
    }

    /**
     * [computeBonus 奖金范围预测]
     * @param  {number} active    [当前选中的号码个数]
     * @param  {string} play_name [当前的玩法标识,如R2,即任二]
     * @return {[type]}           [奖金范围]
     */
    computeBonus(active,play_name){
        const play=play_name.split(''); //得到当前玩法,例如R2，拆成一个数组[R,2]
        const self=this;
        let arr=new Array(play[1]*1).fill(0);
        let min,max;
        if(play[0]==='r'){
            //算最小值
            let min_active=5-(11-active);   //最小命中数。这种彩票的玩法是总共11个号，每次开5个，如果选任8，那就是剩下3个，也就是选的八个里面包含了2个肯定会开的号，则最小命中数就是2
            if(min_active>0){
                if(min_active-play[1]>=0){  //最小命中数减去当前玩法的基数看是不是大于零
                    arr=new Array(min_active).fill(0);
                    min=Calculate.combine(arr,play[1]).length;  //计算最小命中注数
                }else{
                    if(play[1]-5>0&&active-play[1]>=0){ //任五以上，并且多选了注数
                        arr=new Array(active-5).fill(0);
                        min=Calculate.combine(arr,play[1]-5).length;
                    }else{
                        min=active-play[1]>-1?1:0
                    }
                }
            }else{
                min=active-play[1]>-1?1:0;
            }

            //算最大值
            let max_active=Math.min(active,5);
            if(play[1]-5>0){   //任五以上
                if(active-play[1]>=0){
                    arr=new Array(active-5).fill(0);
                    max=Calculate.combine(arr,play[1]-5).length;
                }else{
                    max=0;
                }
            }else if(play[1]-5<0){ //任五以下
                arr=new Array(Math.min(active,5)).fill(0);
                max=Calculate.combine(arr,play[1]).length;
            }else{ //任五
                max=1;
            }
        }
        return [min,max].map(item=>item*self.play_list.get(play_name).bonus) //返回金额范围，使用了es6的map、箭头函数
    }

    /**
     * [combine 组合运算 C(m,n)]
     * 计算注数:选了5个,如果是任二,则注数为C(2,5)=10,如果是任三,则注数为C(3,5)=10
     * @param  {array} arr  [参与组合运算的数组]
     * @param  {number} size [组合运算的基数]
     * @return {[type]}      [计算注数]
     */
    static combine(arr,size){ // arr=[1,2,3,4,5]   size=3。 size表示每一注的数量
        let allResult=[];
        (function f(arr,size,result){//即时运行函数
            let arrLen=arr.length;  //选中的个数
            if(size>arrLen){
                return; //如果长度大于传入的数组的长度，则结束递归
            }
            if(size===arrLen){
                allResult.push([].concat(result,arr))  //组合元素的子集
            }else{  //每注所需号码的数量小于选中数字的总数量时，进行计算
                for(let i=0;i<arrLen;i++){
                    let newResult=[].concat(result);
                    newResult.push(arr[i]);
                    if(size===1){
                        allResult.push(newResult)
                    }else{
                        let newArr=[].concat(arr);
                        newArr.splice(0,i+1);
                        f(newArr,size-1,newResult);   //这里不能用argument.callee
                    }
                }
            }

        })(arr,size,[])
        return allResult
    }

}

export default Calculate
